home *** CD-ROM | disk | FTP | other *** search
/ Aminet 12 / Aminet 12 (1996)(GTI - Schatztruhe)[!][Jun 1996].iso / Aminet / dev / lang / HeliOS4.lha / helios_demo_disk4 / docs / userinterface / Debug.doc < prev    next >
Encoding:
Text File  |  1995-07-05  |  19.0 KB  |  516 lines

  1. ************
  2. The Debugger
  3. ************
  4.  
  5. Debugging consists mainly of locating the area where a problem occurs.
  6.  
  7. Doing this sometimes requires additional information about program
  8. execution, and in these cases the custom HeliOS debugger is very useful.
  9.  
  10. Beware, however, of the common mistake of using a debugger to generate
  11. a lot of extra information which in fact confuses the issue and makes
  12. the task of debugging harder than it need be.
  13.  
  14. Often the simple use of output statements within a program, along with
  15. careful inspection and analysis of the code, is all that is required.
  16.  
  17. HeliOS has a powerful debug facility which can be user-customised to do
  18. almost anything.  This debugger is deceptively simple but very powerful:
  19. it effectively allows you to step through your code checking any aspect
  20. of the system as you go and carrying out any procedure required.
  21.  
  22. You enter DEBUG mode when you press the "DBug" button in the Interpreter,
  23. and you are then in DEBUG mode until you press the same button again.
  24.  
  25. In DEBUG mode you lose the "Stack Display" but gain a few new buttons.
  26.  
  27. The DEBUG functions will be described below in more detail, but first here
  28. is a quick overview of debugger operation.
  29.  
  30. In DEBUG mode the Interpreter goes through a DEBUG "gate" each time it
  31. executes COLON/SEMICOLON threading operations.  At this point you can have
  32. the debugger run your own user-definable HeliOS mini-program(s) to analyse
  33. what your code is doing and print the results for you to see.
  34.  
  35. You can change the debug code at any point in the program, and even have
  36. the debug code change its own subsequent execution function depending on
  37. program action.
  38.  
  39. You can, for example, pause the program, display variables, dump memory,
  40. single step, wait on variable states.........whatever you choose.
  41.  
  42. The debugger has a STEP function which allows you to specify how many times
  43. to skip between actual debug operations.  By default you will debug every
  44. word, but you can change this interactively while your program is running.
  45.  
  46. You can send debug output to the screen or to the "Out" buffer, and while
  47. you are debugging you can send the normal output of the program either to
  48. the screen or the "Out" buffer.  These two options are in the form of a
  49. double toggle - you cannot have debugger AND program output to either one
  50. single output stream, for obvious reasons of general confusion.......
  51.  
  52. The debugger has a fully interactive mode of operation, which means that
  53. you can press any of the debugger control buttons while the program is
  54. executing.  Thus you can press "Dump" to dump a predefined area of memory
  55. at any time while the program executes.  This will halt program execution
  56. as soon as you hit the "Dump" button, and resume when the dump is finished.
  57.  
  58. You can halt a program by using the debug control panel, or by setting
  59. "breakpoints".  The breakpoint mechanism is very flexible, in that you
  60. can control the debug functions either from the control panel buttons or
  61. from programmable functions within the code.
  62.  
  63. At any point you can temporarily pause the debug session by using the
  64. <Space> bar, and you can abort at any time by pressing <Esc>.
  65.  
  66. This is very much a user-definable debugger, which is important since
  67. debugging requires a very flexible approach for particular contingencies.
  68.  
  69. The debug functions include the ability to list to screen a full nested
  70. display of the names of the HeliOS words in any current "thread".
  71.  
  72. By default the debugger runs a very simple standard function which lists
  73. all the levels of the current execution thread and displays stack contents.
  74.  
  75. **************************
  76. Listing the current thread
  77. **************************
  78.  
  79. The debug control word SHOWDEBUGWORD can display the current execution word
  80. or the complete current execution thread.
  81.  
  82. To understand this, you need to see how a threaded interpretive language
  83. such as HeliOS strings together nested command words.
  84.  
  85. Let us assume that you create a word called PRINTHELLO, like this:
  86.  
  87. : PRINTHELLO ." Hello " ;
  88.  
  89. Let us assume then that you create a word called SHOWHELLO, like this:
  90.  
  91. : SHOWHELLO 20 20 CURPUT PRINTHELLO ;
  92.  
  93. Let us assume then that you create a word called SHOWREDHELLO, like this:
  94.  
  95. : SHOWREDHELLO 6 FPENSET SHOWHELLO ;
  96.  
  97. Let us assume then that you create a word called HELLOFRIEND, like this:
  98.  
  99. : HELLOFRIEND SHOWREDHELLO ." Friend!" ;
  100.  
  101. Now let us look what happens when you execute HELLOFRIEND:
  102.  
  103. First the interpreter gets the word HELLOFRIEND and starts to interpret it.
  104.  
  105. The interpreter finds a new word SHOWREDHELLO, so it remembers where it was
  106. in its execution of the word HELLOFRIEND and tries to interpret the new
  107. word SHOWREDHELLO.
  108.  
  109. The interpreter is now at a second nested level, and the current thread
  110. consists of the two words HELLOFRIEND and SHOWREDHELLO.
  111.  
  112. Now the interpreter goes into the word SHOWREDHELLO and starts to interpret
  113. it. Here it will encounter a few execution commands for 6 FPENSET followed
  114. by your word SHOWHELLO.
  115.  
  116. The interpreter has now found yet another a new word SHOWHELLO, so it once
  117. again remembers where it was in all the previous threaded words and starts
  118. to interpret SHOWHELLO.
  119.  
  120. In SHOWHELLO, after the cursor positioning commands the interpreter finds
  121. yet another of your words, called PRINTHELLO.
  122.  
  123. Once again the interpreter remembers where it was and tries to interpret
  124. the latest word PRINTHELLO.
  125.  
  126. The word PRINTHELLO has a simple execution result and requires with no
  127. further threading, so now the interpreter goes back one level and continues
  128. where it left off on the previous threaded command SHOWHELLO.
  129.  
  130. The interpreter will now work its way back out through the thread until
  131. all words have completed.
  132.  
  133. When the interpreter was executing PRINTHELLO, the full thread would look
  134. like this, with a depth of four words:
  135.  
  136. HELLOFRIEND  SHOWREDHELLO  SHOWHELLO  PRINTHELLO
  137.  
  138. The debugger would by default use the debug control word SHOWDEBUGWORD to
  139. display the full thread of the current execution word at each threading
  140. point.
  141.  
  142. Thus if you were to debug the word HELLOFRIEND you would see a series of
  143. statements displaying the threading, step by step, which at one point
  144. would contain "HELLOFRIEND  SHOWREDHELLO  SHOWHELLO  PRINTHELLO" .
  145.  
  146. Try this in the interpreter, making sure that output is enabled to both the
  147. screen AND the buffer.  Allow the execution of the word HELLOFRIEND to
  148. complete, then look at the results in the "Out" editor.
  149.  
  150. You will notice that the word LIT appears every time HeliOS handles a pure
  151. numeric value on the stack.
  152.  
  153. You will also notice some new words used to actually print to the screen.
  154.  
  155. One of these words is called NONAME, which means that it is an internal
  156. HeliOS word with no vocabulary entry.  There are many of these words with
  157. no user name, so in many cases your debug thread displays will contain
  158. multiple instances of words with NONAME.  Do not worry about this.
  159.  
  160. In particular, you fill find NONAME cropping up often when executing core
  161. HeliOS words rather than your own constructed threads.
  162.  
  163. Careful examination of the full thread display in the "Out" editor will
  164. allow you to determine exactly which word is executing at any time and
  165. what the stack contains at this point.
  166.  
  167.  
  168. ******************
  169. Using the debugger
  170. ******************
  171.  
  172. By default the debugger has a very simple debug execution function.
  173.  
  174. If you enter DEBUG mode without setting your own debug function, the
  175. sytem will execute the default debug function at every threading point.
  176.  
  177. The default debug function will, at each threading point:
  178.  
  179. 1. Print out stack contents in red
  180.  
  181. 2. Print out in black a list of the current thread
  182.  
  183. Pressing the <Space> bar will pause the debug operation.
  184.  
  185. Pressing <Space> a second time will restart debugging.
  186.  
  187. Pressing <Esc> will abort debugging at any time.
  188.  
  189. Use the thread display to determine exactly which part of your code is
  190. currently executing.
  191.  
  192. The simple stack display used by default may be enough in many cases, but
  193. remember that you can create your own debug functions to check memory
  194. locations, print variables, etc.  
  195.  
  196. You can write debug words to do whatever you like, and you can use the 
  197. debug control words listed below to control the action of the debugger 
  198. from within your own debug software, allowing great flexibility.
  199.  
  200. The rest is up to you, and how you wish to approach any particular debug 
  201. task.
  202.  
  203. ****************************
  204. Why NOT to use the debugger!
  205. ****************************
  206.  
  207. Strictly speaking, using a debugger is a matter of personal preference,
  208. but in most cases you can debug code more quickly and efficiently by
  209. the intelligent use of print statements from within your code combined with
  210. the use of WAITSPACE commands to allow you to step through your code as it
  211. is executing.
  212.  
  213. This can be far quicker and simpler than using a debugger, and we recommend
  214. that you avoid getting too involved with using the debugger unless you 
  215. really need its powerful capabilities to crack a very difficult bug.
  216.  
  217. You will make more progress in understanding your code if you undertake
  218. to find most bugs by careful inspection of your code along with the display
  219. of vital parameters as your program executes.  In this way you become more
  220. expert in how your own code functions rather than in the intricacies of
  221. setting up complex debugging procedures.
  222.  
  223. Of course, many programmers just love setting up fantastic sophisticated
  224. debug capabilities just for the sake of the feeling of power they get
  225. by squeezing alarming amounts of esoteric information from recalcitrant
  226. and malicious computers.  This can be great fun of course, and constructing
  227. a subtle and cunning debug system to entrap a really nasty bug can be very
  228. satisfying in its own right.
  229.  
  230. ****************************************************
  231. A few simple hints on debugging without the debugger
  232. ****************************************************
  233.  
  234. HeliOS may indeed have a very powerful user-configurable debugger, but for
  235. most debugging you should never need to use it!  The following hints should
  236. be taken as general programming guidelines, and intelligent programming is
  237. preferable to reliance on the debugger.
  238.  
  239. There are a few simple techniques which, combined with sensible programming
  240. strategies (for example, do not write 200k of source code altogether with
  241. no testing then expect it to work instantly...), will enable you to debug
  242. code very simply.
  243.  
  244. When a bug occurs the program will often (probably!) crash.
  245.  
  246. The first stage of debugging is to find exactly at what point in the code
  247. the program goes wrong.
  248.  
  249. One good simple debugging technique is to put a simple repetitive "pause
  250. and print" debug line into the code which allows you to step through the 
  251. program slowly until the point where things go wrong.
  252.  
  253. This "pause and print" line should display the stack status and wait for 
  254. the space bar to be pressed.  
  255.  
  256. Something like the following will do nicely:
  257.  
  258.  ." Now doing xxxxx. Stack reads: " .S ." <SPACE> to continue" WAITSPACE CR
  259.  
  260.  
  261. A few of these lines included in your code will give you a sequential
  262. talk-through until the crash point is reached.
  263.  
  264. Having written the program yourself you should be able to work out quite
  265. well just where in the execution of your code the fault is happening.  
  266.  
  267. Once you know where in the code the problem lies, intelligent examination 
  268. of your code in combination with all the available "clues" will generally
  269. reveal the trouble quite easily.
  270.  
  271. Start with the high level code first and then work into your subroutines:
  272. in this way you can home in on the actual fault.  It is good practice to
  273. check each subroutine thoroughly as it is completed, but nevertheless the
  274. most unexpected results can occur when even apparently sound subroutines
  275. are used together in complex ways.
  276.  
  277. The stack status message debug line suggested above will probably mess up
  278. your program's screen display, but that does not really matter in a debug
  279. operation.
  280.  
  281. Always check for stack aberrations first. Be aware of what the stack should
  282. be reading and check your debug stack readouts scrupulously.
  283.  
  284. If you like, include DUMP commands in your debug instructions to dump areas
  285. of memory for careful scrutiny.  Displaying variables is also useful, as is
  286. the creation of special debug "flag" variables which you can use to warn
  287. you of various internal states of your program.
  288.  
  289. There are so many ways for code to fail it is impossible to cover all the
  290. aspects of debugging.  Debugging is a very intuitive thing and everyone
  291. has very personal preferences.
  292.  
  293. The main thing is to never assume ANYTHING to be OK without double checking,
  294. and be prepared to be patient and check EVERYTHING relating to your problem
  295. with an open mind.
  296.  
  297. Check your stack dumps minutely, dump and also check any areas of memory
  298. you think may be suspect, check variable values by including them in your
  299. debug lines where appropriate.
  300.  
  301. One big source of trouble is using address pointers which should really be
  302. pointing at something useful like a screen structure address, but actually
  303. contain zero.  A golden rule on a multitasking machine like the Amiga is
  304. never to assume that an allocation or opening routine must always succeed.
  305. Always check to see if everything has opened correctly, and always take
  306. care to initialise all fields of data structures correctly.
  307.  
  308.  
  309. *******
  310. Warning
  311. *******
  312.  
  313. Sometimes using the debugger can have unpredictable results with certain 
  314. types of code, so use it carefully and ensure that your work is saved 
  315. before starting to debug complex code.
  316.  
  317. You may often find that you want to debug software where the screen output
  318. of the debugger will cause conflicts with the program execution.  In these
  319. cases you may wish to supply your own debug function or switch off output
  320. to the screen.
  321.  
  322. It is a good idea to always switch off the debugger except when you are
  323. actually using it.
  324.  
  325.  
  326. *****************
  327. Debugger controls
  328. *****************
  329.  
  330. *****************
  331. The "DBug" button
  332. *****************
  333.  
  334. This changes the stack display bar into a set of debugger control buttons
  335. and simultaneously enters debug mode.  You will then be in debug mode until
  336. you press the "DBug" button again, which reverts to normal interpretation.
  337.  
  338.  
  339. Debug control buttons:
  340.  
  341. *************
  342. Screen Output
  343. *************
  344.                - These buttons toggle debugger output streams
  345. *************
  346. Buffer Output
  347. *************
  348.  
  349. The idea here is that when in debug mode, your program's normal screen
  350. output will be stopped, and the screen will be used by the debugger to
  351. print debug messages.  Similarly the "Out" buffer will get debug output.
  352.  
  353. If you switch off either of the Screen/Buffer output buttons, the normal
  354. program output will be sent to that output stream rather than the debug
  355. output.  Thus you can choose which output you want to see, and can view
  356. one output while sending the other to the "Out" buffer.
  357.  
  358. These buttons can be pressed as your program is executing so that you can
  359. alternate between output modes at will during a debugging session.  This
  360. gives great flexibility to the system.
  361.  
  362. What is perhaps even more useful is that the output streams can be changed
  363. under program control by your debug routines within the executing program.
  364.  
  365. This system gives you a lot of control and choice over the posting of
  366. debugger information.
  367.  
  368. **********************************************
  369. The "Step" button and associated string gadget
  370. **********************************************
  371.  
  372. The step string gadget lets you set how many times the debugger will "skip"
  373. between calls to the debug routines.  A setting of "1" will cause the debug
  374. code to be run for every threaded word, a setting of "4" will sample every
  375. fourth threading etc.
  376.  
  377. Again this can be altered at will as the program executes, and can also be
  378. changed by the debug software.  Thus you could insert debug routines which
  379. step through certain sections of code in large jumps until a "vital" part
  380. of the program is reached, whereupon the debugger could be made under the
  381. control of software to "automatically" change to single stepping.
  382.  
  383. The "Step" button, if switched "On", will cause the software to pause at
  384. each debug entry point rather than free running.  Thus you can skip parts
  385. of a program and return to debug "paused" mode by entering a certain value
  386. into the string gadget, setting "Step" to "On", then pressing "Run".
  387.  
  388. Again this can be done interactively while the program is executing or
  389. from within the software under debug program control.
  390.  
  391. ****************
  392. The "Run" button
  393. ****************
  394.  
  395. This starts the program executing after you have paused within debug mode.
  396.  
  397. This function is also available from program control.
  398.  
  399. ******************
  400. The "Pause" button
  401. ******************
  402.  
  403. This stops the program executing and pauses within debug mode.
  404.  
  405. Pressing the <Space> bar will also pause the debug operation.
  406.  
  407. Pressing <Space> a second time will restart debugging.
  408.  
  409. Pressing <Esc> will abort debugging at any time.
  410.  
  411. This function is also available from program control.
  412.  
  413.  
  414. ******************
  415. The "Abort" button
  416. ******************
  417.  
  418. This aborts the debug session and quits the program.
  419.  
  420. Pressing <Esc> will abort debugging at any time.
  421.  
  422. Pressing the <Space> bar will pause the debug operation.
  423.  
  424. Pressing <Space> a second time will restart debugging.
  425.  
  426. This function is also available from program control.
  427.  
  428.  
  429. **********************************************
  430. The "Dump" button and associated string gadget
  431. **********************************************
  432.  
  433. This button lets you set up an address for a memory dump which can be
  434. carried out by pressing the "Dump" button at any time while the program
  435. is executing.
  436.  
  437. This function is also available from program control.
  438.  
  439.  
  440. **********************
  441. Debugger control words
  442. **********************
  443.  
  444. There are several HeliOS words which control the action of the debugger
  445. from within your program.  These words can be used to set up breakpoints
  446. and conditional debugging etc.
  447.  
  448.  
  449. ********
  450. SETDEBUG   ( cfa [or 0] - - - )
  451. ********
  452.  
  453. Used in the form:
  454.  
  455. FIND MYDEBUGWORD SETDEBUG  -> Makes MYDEBUGWORD the subsequent debug action
  456.  
  457. 0 SETDEBUG                 -> Restores the system default debug action
  458.  
  459.  
  460. *************
  461. GETDEBUGLEVEL  ( - - - n1 )
  462. *************
  463.  
  464. Returns n1, the current depth, or level, of the threaded interpreter.
  465. You can use this word to determine how many nested levels deep your
  466. current execution word lies.
  467.  
  468. *************
  469. SHOWDEBUGWORD  ( n1 - - - )
  470. *************
  471.  
  472. This word will print to screen the name of the HeliOS word which lies
  473. at level n1 in the current execution thread.
  474.  
  475. If you use a value of "n1 = -1", a full list of the full execution thread
  476. will be printed.  This is the default used by the system debug word.
  477.  
  478. *************
  479. SETDEBUGPAUSE  ( - - - )
  480. *************
  481.  
  482. Acts like the debug "Pause" button to enter debugger paused state.
  483.  
  484. *************
  485. SETDEBUGABORT  ( - - - )
  486. *************
  487.  
  488. Acts like the debug "Abort" button to abort the debug session.
  489.  
  490. **************
  491. SETDEBUGSCREEN ( n1 - - - ) where n1 = switch (1 for "On", 0 for "Off")
  492. **************
  493.  
  494. Acts like the debug "Screen" button to toggle screen output mode.
  495.  
  496. **************
  497. SETDEBUGBUFFER ( n1 - - - ) where n1 = switch (1 for "On", 0 for "Off")
  498. **************
  499.  
  500. Acts like the debug "Buffer" button to toggle buffer output mode.
  501.  
  502.  
  503. *********
  504. SETDEBUG#  ( n1 - - - )
  505. *********
  506.  
  507. Inserts a number n1 into the debug step number string gadget and updates
  508. the step number.
  509.  
  510.  
  511. ************
  512. SETDEBUGSTEP ( n1 - - - )  where n1 = switch (1 for "On", 0 for "Off")
  513. ************
  514.  
  515. Sets the current status of the debug "Step" button.
  516.